package csel.model;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Model
{
	public static final boolean infoMode = false;
	
	private LoaderSaver _loaderSaver;
	private GameData _gameData;
	private ArrayList<Observer> observers = new ArrayList<Observer>();

	public Model()
	{
		_loaderSaver = new SerializationLoaderSaver();
	}
	
	public void accept(GameCommand command)
	{
		System.out.println("[MODEL] Got GameCommand: " + command.toString());
		command.execute();
	}

	public boolean load(String fileName) throws IOException, FileNotFoundException
	{
		GameData newGameData;
		
		newGameData = _loaderSaver.load(fileName);

		/* THIS IS A HACK -- david */
		newGameData.get_playerEntity().getInventory().setHasChanged(true);
		
		set_gameData(newGameData);
		
		newGameData.getChronoTrigger().start();

		return true;
	}

	public boolean save(String fileName) throws IOException, FileNotFoundException
	{
		_loaderSaver.save(fileName, _gameData);
		return true;
	}
	
	/**
	 * Stops all actions occurring with the game. Something like an eternal pause.
	 */
	public void stopGame()
	{
		_gameData.getChronoTrigger().stop();
	}
	
	/* Game Data accessors */

	public List<Entity> getEntities()
	{
		return _gameData.get_entities();
	}

	// please implement me!
	// eh... maybe later
	public Entity getPlayerEntity()
	{
		return _gameData.get_playerEntity();
	}

	public Map getMap()
	{
		return _gameData.get_map();
	}

	GameData get_gameData()
	{
		return _gameData;
	}

	/**
	 * This is only for Factory use.
	 */
	void set_gameData(GameData data)
	{
		if (_gameData != null)
			_gameData.cleanup();
		
		_gameData = data;

		notifyO();    // notify _after_ game completely finished loading
	}

	public void addObserver(Observer o)
	{
		observers.add(o);
	}
	
	public boolean removeObserver(Observer o)
	{
		return(observers.remove(o));
	}
	
	protected void notifyO()
	{
		System.out.println("[MODEL] Notifying Model Observers.");
		
		for(Observer o: observers)
		{
			o.modelUpdate(this);
		}
	}
}
